package app;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class XMLGenerator {

	private Document doc;

	private File file;
	private long depth;

	private long width;
	
	public XMLGenerator(File file) throws ParserConfigurationException{
		this.file = file;
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		doc = db.newDocument();
	}
	
	private void addChildren(Element el, boolean binary, boolean full, int currentDepth){
		long width;
		
		int random = getRandom(1,10);
		
		if(currentDepth >= depth)
			return;
		
		if(binary){
			width = 2;
		}else{
			width = this.width;
		}
		

		
		for(long i = 0; i < width; i++){
			Element element = doc.createElement("Node"+i+""+currentDepth);
			el.appendChild(element);
			
			if(!full && i == random)
				break;				
		}
		
		for(Node childNode = el.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()){
			addChildren((Element) childNode, binary, full, currentDepth+1);
		}
		
	}
	
	public void generate(long depth, long width, boolean full, boolean binary){
		this.depth = depth;
		this.width = width;
		Element root = doc.createElement("Root");
		doc.appendChild(root);
		addChildren(root, binary, full, 0);
					
		writeToFile(file);
	}
	
	private int getRandom(int low, int high) {
		return (int) (Math.random() * (high - low) + low);
	}

	private String getContent() throws TransformerException {
        //set up a transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        //create string from xml tree
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(doc);
        trans.transform(source, result);
        String xmlString = sw.toString();
        
        return xmlString;
	}
	
	private void writeToFile(File file) {
		try { 
			OutputStream out = new FileOutputStream(file);
			OutputStreamWriter osw = new OutputStreamWriter(out);
			osw.write(this.getContent());
			osw.close();
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}	
	}
}
